Request for feedback: proposed new Perl modules to aid VHDL projects

  • Thread starter Michael Attenborough
  • Start date
M

Michael Attenborough

I have a set of Perl modules that I have developed, originally for my own
needs,
to help build and compile VHDL projects with the ModelSim simulator.
I have posted in comp.lang.perl.modules mainly for feedback on module
naming, and I'm also posting here to check there is a need for these
modules, and that I'm not otherwise wasting my time.

What the module set does (general)
===
* Performs a minimal recompile of a VHDL project using ModelSim, recompiling
only those design units which have changed, and those which depend on them.
No need to write and maintain compilation scripts or Makefiles.
* Feeds source files through a preprocessor if wanted (preprocessors are
selected by the first line of the source file, and are implemented as
pluggable modules).
* References any compiler errors back to the correct source file and line
number.
* Component declarations can be automatically inserted, removing the need to
cut-and-paste each time an entity is changed.
* Compiler options can be set using special commands in comments in the
source files

What the module set does (detail)
===
To use the modules you need to create a "project" object, and tell it the
filenames of the source files that you want it to work with, and locations
of some working directories. To do a project build, the project object
needs to go through two stages, a "generate" stage and a "compile" stage.
The "generate" stage involves finding which of the source files have
changed, by checking modification times, and where needed passing them
through a preprocessor and then splitting the code up into individual files
for each design unit. Component declaration insertions are done as a second
pass (this is not a preprocessor function).
The "compile" stage looks at the ModelSim library data to find dependencies
between design units, and to identify the compiled data file for each design
unit, then it calls the ModelSim compiler to recompile all the out-of-date
design units.

The program design is UI-agnostic: status reports are done via callbacks,
and errors via exceptions (well, it croaks). I started writing a Tk front
end, and this was fine, but in practice I have found it more useful to just
have a perl script to update the source files (add all files from my 'src'
directory) when I need to, and for general development I just hit F7 in my
text editor (I use SciTE) and have that set up to do the "generate and
compile". I can then double-click on any error messages to jump to the
offending line in the source file.

Module structure and proposed names
===
Generally, I'm proposing to put reusable VHDL-language-related components
under Hardware::Vhdl (this hierarchy already exists, and contains the only
VHDL-specific module on CPAN) and the various components of my build tool
under Hardware::Vhdl::Automake.
My development modules are called:
Hardware::Vhdl::Lexer - returns lexical tokens one-by-one from a VHDL
source file. This is needed by my automake tool, but may be useful for
other purposes (like a Hardware::Vhdl::Tidy module that I have in mind)
Hardware::Vhdl::Automake::project - defines a project class; instances
of this hold information about source files, design units, working
directories and compilation status, using instances of some of the classes
below.
Hardware::Vhdl::Automake::SourceFile - defines a class that stores
information about a source file, and methods do split it into design units,
etc.
Hardware::Vhdl::Automake::DesignUnit - defines a class that stores
information about a design unit, its compiler options and its compilation
state
Hardware::Vhdl::Automake::UnitName - defines a class to store and
manipulate design unit names
Hardware::Vhdl::Automake::preProcessor - deals with preprocessing files
(calls preprocessor plugins if requested) and returning them line-by-line
Hardware::Vhdl::Automake::preProcessor::* - preprocessor plugins. I
will include one called Cish[1] that is like the CPP preprocessor, and it
should be possible to write plugins to call m4, Text::CPP, Text::EP3 etc.
Hardware::Vhdl::Automake::CompileTool - base class for compiler plugins
Hardware::Vhdl::Automake::Compiler::ModelSim - a compiler plugin for
ModelSim.
All of these use an OO API. All the classes do provide methods as well as
data storage.

Scope
===
The modules currently only support the ModelSim simulator, because that is
the one that I have, but I've tried to structure things so that one can plug
in modules to support other compilers (or possibly synthesis tools).
The use of Verilog source files is not currently supported: it's mainly the
"generate" stage that would need to be added.

So, any comments, particularly regarding the module names? For example,
should I use something other than Hardware::Vhdl, because the tool may
support Verilog too at some point in the future?

[1] I ended up writing this because Text::CPP doesn't work on Win32, and
Text::EP3 has some important omissions. If it later seems worthwhile to
create Text::CishPP (or whatever I call it) as a generic preprocessor then
Hardware::Vhdl::Automake::preProcessor::Cish will become just a plugin
interface to it.
 
M

Mike Treseler

Michael said:
I have a set of Perl modules that I have developed, originally for my own
needs,
to help build and compile VHDL projects with the ModelSim simulator.
I have posted in comp.lang.perl.modules mainly for feedback on module
naming, and I'm also posting here to check there is a need for these
modules, and that I'm not otherwise wasting my time.

Thanks for sharing your work.
Many in this group have expressed interest in preprocessing.
Check the link below for more ideas on
project scope definition, multiple simulator support
and makefile generation.

http://opensource.ethz.ch/emacs/vhdl-mode.html

I use vhdl-mode macros from the command line in my test scripts.
You could borrow a few features from it.

-- Mike Treseler
 
A

Allan Herriman

On Fri, 24 Feb 2006 14:52:58 -0000, "Michael Attenborough"

[snip]
* Component declarations can be automatically inserted, removing the need to
cut-and-paste each time an entity is changed.

Do people still use these?

I stopped using component declarations when tools started to support
VHDL-93 properly (in about 2000?).
There are obvious exceptions when you really need to use a component
declaration, e.g. black boxes and some configurations, but these are
/relatively/ uncommon.

Allan
 
M

Mike Treseler

Allan said:
Do people still use these?

Yes, the average designer gets
training and examples from
brand X and A, who have a vested
interest in black boxes.

The common response I get from
designers I know is,

"Yes, I have heard about direct instances,
but I won't have time to try anything
new until I finish $some_project"

So it goes. Creatively wasting time
is really the only way to ever catch up.

-- Mike Treseler
 
A

Allan Herriman

Yes, the average designer gets
training and examples from
brand X and A, who have a vested
interest in black boxes.

The common response I get from
designers I know is,

"Yes, I have heard about direct instances,
but I won't have time to try anything
new until I finish $some_project"

So it goes. Creatively wasting time
is really the only way to ever catch up.

At the time, I was fortunate enough to be in a reasonably senior
position in a large group of designers in a large company. It was as
simple as testing it out against the set of tools we used, making some
power point presentations and writing it into what passed for a coding
standard.
Direct instantiation was adopted quite quickly, as all designers hated
component declarations.

Actually, this is probably a good reason to avoid all textbooks and
coding guides from the 1990s. (The same applies to Verilog - there
were some significant fixes to the language in the 2001 edition, and
the old documentation doesn't mention them.)

Regards,
Allan
 
M

Michael Attenborough

Allan Herriman said:
On Fri, 24 Feb 2006 14:52:58 -0000, "Michael Attenborough"

[snip]
* Component declarations can be automatically inserted, removing the need to
cut-and-paste each time an entity is changed.

Do people still use these?

I stopped using component declarations when tools started to support
VHDL-93 properly (in about 2000?).
There are obvious exceptions when you really need to use a component
declaration, e.g. black boxes and some configurations, but these are
/relatively/ uncommon.

Interesting - I got my training from Esperan in 1999 and I don't think that
direct instantiation was ever mentioned. I only came across it when I was
looking though a VHDL reference guide to research my Perl-based build
system. Perhaps I need some update training - I've read the FAQ entry but I
don't understand it (what does it mean to instantiate an "entity interface"
as opposed to an architecture?).

Anyway, to return to the original point, my Perl modules make it easy to do
component declarations if you want or need them, but they are in no way
obligatory.

Michael A
 
M

Michael Attenborough

Mike Treseler said:
Many in this group have expressed interest in preprocessing.
Check the link below for more ideas on
project scope definition, multiple simulator support
and makefile generation.

http://opensource.ethz.ch/emacs/vhdl-mode.html

I use vhdl-mode macros from the command line in my test scripts.
You could borrow a few features from it.

Thanks, that does look interesting.
It's a shame I can't read Lisp, I'd be interested in the algorithm that
parses out the instantiation tree. I thought I might need to do this (and I
may yet, eventually) but for the moment I am cheating and parsing the
ModelSim _info files instead. This restricts me to using ModelSim (which
this is fine for my needs) but has great advantages in simplicity and
probably also in processing speed. It does work across multiple design
libraries, by the way.
I had to parse the _info files in any case, to get the name of the compiled
binary files for up-to-date-ness checking. I'll have to check that my
parsing works across a good range of ModelSim versions.

Michael A
 
A

Allan Herriman

Allan Herriman said:
On Fri, 24 Feb 2006 14:52:58 -0000, "Michael Attenborough"

[snip]
* Component declarations can be automatically inserted, removing the need to
cut-and-paste each time an entity is changed.

Do people still use these?

I stopped using component declarations when tools started to support
VHDL-93 properly (in about 2000?).
There are obvious exceptions when you really need to use a component
declaration, e.g. black boxes and some configurations, but these are
/relatively/ uncommon.

Interesting - I got my training from Esperan in 1999 and I don't think that
direct instantiation was ever mentioned. I only came across it when I was
looking though a VHDL reference guide to research my Perl-based build
system. Perhaps I need some update training - I've read the FAQ entry but I
don't understand it (what does it mean to instantiate an "entity interface"
as opposed to an architecture?).

The "entity interface" is just the list of ports and generics.

The instantiation in your source code looks pretty much the same.

my_label : entity my_lib.my_entity
port map(...);

or
my_label : entity my_lib.my_entity(my_architecture)
port map(...);

instead of

my_label : my_lib.my_component
port map(...);


Pros:
- You don't need a component declaration.

Cons:
- You can't apply a configuration to this instantiation.
- The entity declaration must already be compiled into the library
prior to compiling the architecture which instantiates the entity.
- It doesn't work with black boxes.

Anyway, to return to the original point, my Perl modules make it easy to do
component declarations if you want or need them, but they are in no way
obligatory.

That's good to know.

Regards,
Allan
 
M

Mike Treseler

Michael said:
Thanks, that does look interesting.
It's a shame I can't read Lisp,

I have picked up some just by running commands
then looking at the source code. A simple function
is little more than a list of commands in parens.
I'd be interested in the algorithm that
parses out the instantiation tree.

Once I have defined the project directories,
vhdl-mode reparses the tree whenever I save
a file or drill down in the browser (speedbar)
This can take a few seconds the first time,
but it is in cache after that. It also
reports duplicate unit names in the message buffer
-- a good verification for QAing the CVS repository.
I thought I might need to do this (and I
may yet, eventually) but for the moment I am cheating and parsing the
ModelSim _info files instead.

vhdl-mode can infer the work directory unit structure
from the instance tree. This is necessary to generate
a Makefile without first doing a compile manually.
This is a huge advantage for testing a multi-user CVS
repository.
This restricts me to using ModelSim (which
this is fine for my needs) but has great advantages in simplicity and
probably also in processing speed.

If you can just cover one, Modelsim is the logical choice.
It does work across multiple design
libraries, by the way.

You score one here.
vhdl-mode covers only one library,
so I have to throw the odd "vmap altera_mf work"
into my scripts to cover vendor library references
other than work. I have to watch the message
buffer for unit name collisions that could result,
but so far, these have all been due to
designers checking in the same entity name twice.
I had to parse the _info files in any case, to get the name of the compiled
binary files for up-to-date-ness checking.

vhdl-mode defines these targets when I do a
(vhdl-generate-makefile) but leaves the
date-checking up to make.

-- Mike Treseler
 
M

Mike Treseler

Martin said:
Hi Mike,
I'm intrigued - what do your test-scripts do that vhdl-mode helps
with?

QA on a CVS repository.
I do a clean checkout then invoke an emacs macro
something like this:
emacs -f makemake
where the function below is declared in my ~/.emacs:

(defun makemake() "Generate Makefile from command line"
(interactive)
(vhdl-mode)
(vhdl-speedbar)
(vhdl-set-project "qa")
(speedbar-change-initial-expansion-list "vhdl project")
(vhdl-generate-makefile)
(kill-emacs)
)


-- Mike Treseler
 
M

Mike Treseler

Allan said:
The instantiation in your source code looks pretty much the same.
my_label : entity my_lib.my_entity
port map(...);
or
my_label : entity my_lib.my_entity(my_architecture)
port map(...);

Thanks for the soapbox Allen.

I had forgotten about that second form.
Note that if I ever had a
reason to select architectures,
the direct method shown above
is much simpler and easier to read
than the equivalent configuration.
Pros:
- You don't need a component declaration.

Yes. Components are a big annoyance for me in dealing
with code by others. Why do double maintenance
on all the sub-entity port lists to maintain
default binding when no configurations or black-boxes are
used? Doooh!
Cons:
- You can't apply a configuration to this instantiation.

This feature is rarely used for synthesis.
For testbenches, I prefer generic options.
- The entity declaration must already be compiled into the library
prior to compiling the architecture which instantiates the entity.

If am blocking out a new design from the top,
I can just as easily declare and
instance the real entities with null architectures
to make my top-down block diagram.

With a top-down design using unbound components
I have to ignore binding warnings
until the real entities exist, and
then I have to maintain the component
declarations forever because no one
ever has the heart to delete a venerable
component for a direct instance.
- It doesn't work with black boxes.

With the exception of analog things
like PLLs, most of the black boxes I see
could be replaced with a few lines of code.

-- Mike Treseler
 
A

Allan Herriman

Thanks for the soapbox Allen.

I had forgotten about that second form.
Note that if I ever had a
reason to select architectures,
the direct method shown above
is much simpler and easier to read
than the equivalent configuration.


Yes. Components are a big annoyance for me in dealing
with code by others. Why do double maintenance
on all the sub-entity port lists to maintain
default binding when no configurations or black-boxes are
used? Doooh!


This feature is rarely used for synthesis.
For testbenches, I prefer generic options.


If am blocking out a new design from the top,
I can just as easily declare and
instance the real entities with null architectures
to make my top-down block diagram.

With a top-down design using unbound components
I have to ignore binding warnings
until the real entities exist, and
then I have to maintain the component
declarations forever because no one
ever has the heart to delete a venerable
component for a direct instance.


With the exception of analog things
like PLLs, most of the black boxes I see
could be replaced with a few lines of code.

Black boxes are also useful for mixed language designs (e.g.
instantiating a Verilog module in your VHDL) or for instantiating IP
cores.
In the past I have used them when independently compiling parts of the
hierarchy. I think I only ever did that when confronted with
synthesiser bugs, and I haven't had to use that trick for years.

Regards,
Allan
 
M

Michael Attenborough

Mike Treseler said:
Note that if I ever had a
reason to select architectures,
the direct method shown above
is much simpler and easier to read
than the equivalent configuration.

I'm in the process of switching from graphical design entry to text-only
(which is what inspired me to write these Perl modules) and I'm feeling my
way around the best way to use configurations.
So far, I am using them for two things:
1) Selecting between a fast RAM-block model which uses integer variables for
data storage and a slow-but accurate FPGA vendor's model
2) Switching the testbench's device-under-test between the RTL and the
gate-level model.

Configuration declarations don't seem to be serving me well for either
case...
1) Including all the hierarchy information to specify where the RAM blocks
are instantiated is a real pain, what with having to include all the entity
and instance names and generates.
2) This seemed good, but I couldn't actually get it to work because the RTL
had generics but the GLM did not. While a configuration declaration lets
you change the generic and port mapping, it doesn't seem to let me specify
"no generics" for an instantiation: "generic map ( )" is an error.

And if I'm considering configuration specifications instead, which means I
need to edit source recompile to change the architecture selection, it seems
I might as well use direct instantiation.
Using a preprocessor could be a nice way to control this (although it still
needs a recompile): I could have a file which defines macros for the RAM
architecture that I want, and include in any file where I instantiate a RAM
block.

in uart.vhd:
#include "arch_config.vhdh"
...
txfiforam : entity ram.dpram(RAM_ARCH) generic map (...

in arch_config.vhdh:
#define RAM_ARCH fast_int_model
Yes. Components are a big annoyance for me in dealing
with code by others. Why do double maintenance
on all the sub-entity port lists to maintain
default binding when no configurations or black-boxes are
used? Doooh!

<salesman_mode> If you were using my build system, you would just need to
replace their component declaration for uart.switch_uart with "--<
component uart.switch_uart >--", for example, and no further maintenance
would be needed, or indeed any manual replacement of instantiations by
direct instantiation. said:
This feature is rarely used for synthesis.
For testbenches, I prefer generic options.

Do you mean you would put in an "if MY_GENERIC=1 generate..." to select
between architectures? That's an idea, for testbenches at least.

Michael A
 
M

Martin Thompson

<some things you can do with vhdl-mode>

Thanks - another tool for the box! And another reason I'm glad I
chose emacs as my editor...

Cheers,
Martin
 
M

Mike Treseler

Michael said:
I'm in the process of switching from graphical design entry to text-only
(which is what inspired me to write these Perl modules) and I'm feeling my
way around the best way to use configurations.
So far, I am using them for two things:
1) Selecting between a fast RAM-block model which uses integer variables for
data storage and a slow-but accurate FPGA vendor's model
2) Switching the testbench's device-under-test between the RTL and the
gate-level model.

I expect that either of these could be handled
using a boolean generic selecting
one of two direct instances in the testbench.
Something like
IF fast_c generate ...
IF not fast_c generate ...
While a configuration declaration lets
you change the generic and port mapping, it doesn't seem to let me specify
"no generics" for an instantiation: "generic map ( )" is an error.

You could assign generic defaults for this
case and and just leave out the map.
Do you mean you would put in an "if MY_GENERIC=1 generate..." to select
between architectures? That's an idea, for testbenches at least.

I don't see why not.
I rarely do gate sims, but this might make a good example.
I do use generics to select testbench tests from the command line.
That works fine.

-- Mike Treseler
 
A

Allan Herriman

I'm in the process of switching from graphical design entry to text-only
(which is what inspired me to write these Perl modules) and I'm feeling my
way around the best way to use configurations.
So far, I am using them for two things:
1) Selecting between a fast RAM-block model which uses integer variables for
data storage and a slow-but accurate FPGA vendor's model
2) Switching the testbench's device-under-test between the RTL and the
gate-level model.

Configuration declarations don't seem to be serving me well for either
case...
1) Including all the hierarchy information to specify where the RAM blocks
are instantiated is a real pain, what with having to include all the entity
and instance names and generates.
2) This seemed good, but I couldn't actually get it to work because the RTL
had generics but the GLM did not. While a configuration declaration lets
you change the generic and port mapping, it doesn't seem to let me specify
"no generics" for an instantiation: "generic map ( )" is an error.

And if I'm considering configuration specifications instead, which means I
need to edit source recompile to change the architecture selection, it seems
I might as well use direct instantiation.
Using a preprocessor could be a nice way to control this (although it still
needs a recompile): I could have a file which defines macros for the RAM
architecture that I want, and include in any file where I instantiate a RAM
block.

in uart.vhd:
#include "arch_config.vhdh"
...
txfiforam : entity ram.dpram(RAM_ARCH) generic map (...

in arch_config.vhdh:
#define RAM_ARCH fast_int_model


<salesman_mode> If you were using my build system, you would just need to
replace their component declaration for uart.switch_uart with "--<
component uart.switch_uart >--", for example, and no further maintenance
would be needed, or indeed any manual replacement of instantiations by


Do you mean you would put in an "if MY_GENERIC=1 generate..." to select
between architectures? That's an idea, for testbenches at least.

Yet another way is to leave out the architecture specification
altogether. VHDL will use whatever architecture has been most
recently compiled into the library.

So compile your RTL source then compile (*) and elaborate your
testbench. It will pick up the RTL version in the library.
Then compile your gate level source then compile and elaborate your
testbench. It will pick up the gate level version in the library.

Crude, but effective as long as you don't want to simulate your RTL
and gate level designs simultaneously.

(*) Note: strictly speaking you don't need to recompile your testbench
if only the dut architecture is being recompiled. However, most of
the time the dut entity declaration will be compiled along with the
dut architecture (because they're in the same file) and the tools
require that the testbench be recompiled.

Regards,
Allan
 
M

Mike Treseler

Allan said:
So compile your RTL source then compile (*) and elaborate your
testbench. It will pick up the RTL version in the library.
Then compile your gate level source then compile and elaborate your
testbench. It will pick up the gate level version in the library.
Crude, but effective as long as you don't want to simulate your RTL
and gate level designs simultaneously.

After writing a generic rtl/gate testbench example, I must agree
that Allan's method is preferable.

The generic switch works ok, but it really makes
a mess of the testbench and causes annoying warnings about
the generated instances driving the same ports.
And flipping the switch requires either a command line
-G option or an edit of the constant assignment.

For me, a gate level sim is an exception rather than
the rule and it is not worth the impact to my standard
design flow to try and support it directly in the
testbench source. A little script using Allan's method
is probably the best way to go.

-- Mike Treseler
 
M

Michael Attenborough

Mike Treseler said:
I expect that either of these could be handled
using a boolean generic selecting
one of two direct instances in the testbench.
Something like
IF fast_c generate ...
IF not fast_c generate ...

In the case of the RAM model selection, this means changing all the entities
in the instantiation path so that I can thread a 'generic' value through to
them - yuck. Possibly an feasible option for the device-under-test
selection, though - although here, the configuration is fairly simple to
write, and arguably neater.
You could assign generic defaults for this
case and and just leave out the map.

That doesn't work, because the default generics (from the RTL entity) are
not what I want: I want no generics when I am plugging in the gatelevel
model in place of the RTL. ModelSim gives me an error "Entity does not have
a generic named xxx" when I try to compile the configuration without a
generic map. I can define a completely different generic map if I want, but
I don't know how to specify an empty generic map. An omisssion from the
language spec?
Cons:
- You can't apply a configuration to this [direct] instantiation.

As far as I can see, I also can't apply a configuration to anything below a
directly instantiated entity/architecture in the instantiation tree - is
this true, or is it that I just don't know the correct syntax to do it?

Michael A
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top