VHDL is a crazy rich language but with crazy idiosyncrasies... It tries to enforce "good practices" by promoting certain constructs and banning others, which can make your life harder sometimes.
Here I want to speak about the crown jewels of the library : a system that takes arbitrary logic/boolean circuits (implemented with this very library only), extracts the netlist and generates a small set of test vectors.
This is not really a "black box" approach because we have the source code but I don't want to even have to consider analysing it, this would mean digging into GHDL-specific features and a long-term risk. Thanks to this library, I can use a "grey box" approach because I can access the inputs and outputs. Somehow. It's not a panacea but enough to get us going in the right direction.
The early idea looks like this :
We have the D.U.T. integrated in the VG program/entity through a wrapper that transforms the bunch of wires into a couple of bland std_logic_vectors. Our vector algorithm won't care a bit about what's inside or how to interface to it, it's all just bits to read and write...
There is just one little big problem: the number of input and output bits is usually given by a generic parameter/number, but here it is provided "from the inside out" (or bottom-up) by the DUT/Wrapper, while VHDL "promotes" the reverse : generics enforce the top-bottom hierarchy and are provided by the top-level entity. Which can't guess in advance what's inside...
One could use configurations or even external generics but I want to keep the whole thing as lean and easy to use as possible. Ideally, the Wrapper would be generated automatically though at this stage, it's much faster and easier to do it by hand. Later I'll find how GHDL can help, as Tristan told me.
One natural solution is to change the hierarchy.
Now the wrapper encapsulates the whole thing, instead of being a mere translator/connector. A tiny advantage is that the DUT gets one level higher in the hierarchy, which will shorten the logs (a bit). There are two small wrinkles though:
- The wrapper should be as lean as possible, and easily computer-generated. If the VG is integrated, it adds complexity and any change in its interface (for control and reporting for example) will force a redesign of the wrapper and the wrapper generator...
- The order of inclusion matters. A lot. The wrapper has the burden of preserving it.
I return back to the first hierarchy with a twist : I let the system auto-configure itself through some simple tricks....
This system leaves the wrapper (and its generator) free from any consideration about the top level, by just routing a few wires here and there. The generics go in the right direction now and the vector generator could implement as many inputs and outputs as desired, and even more. The initial phase simply loops over the in and out vectors to determine the number of used bits, it doesn't take much time anyway, before it does the rest of the useful work.
Sounds like a good plan.
And here is the full source code for the wrapper of INC8 :
-- A3Pv2.6/test2_INC8/Wrap_INC8.vhdl -- version dim. déc. 8 08:07:34 CET 2019 : forked from INC8_tb.vhdl -- -- Released under the GNU AGPLv3 license Library ieee; use ieee.std_logic_1164.all; Library work; use work.all; entity VG_Wrapper is generic ( VectGenWidthIn : integer := 9; VectGenWidthOut: integer := 10 ); port( VectIn : in std_logic_vector(VectGenWidthIn -1 downto 0); VectOut: out std_logic_vector(VectGenWidthOut-1 downto 0); VectClk: in std_logic ); end VG_Wrapper; architecture Wrap_INC8 of VG_Wrapper is begin dut: entity INC8 port map ( -- here we "wire" the unit to the Vector Generator ports: A => VectIn(7 downto 0), Y => VectOut(7 downto 0), V => VectOut(8) ); -- the wires for "autoconfig": VectOut(9) <= '1'; VectOut(VectGenWidthOut-1) <= VectIn(8); end Wrap_INC8;
That's it !
As the name says, it's just a wrapper so nothing weird or complicated and it can easily be copy-pasted or generated by a program.