#include #include "system/bsdl_model.hpp" #include "system/parts.hpp" #include "system/pins.hpp" #include "system/pin_spec.hpp" // Minimal synthetic BSDL: 4 TAP pins, one bidir I/O, a power and a ground // linkage pin, each with a PIN_MAP ball. static const char DEMO_BSDL[] = "entity DEMO is\n" " generic (PHYSICAL_PIN_MAP : string := \"PKG\");\n" " port (\n" " TCK:in bit; TDI:in bit; TDO:out bit; TMS:in bit;\n" " IO1:inout bit;\n" " VDD:linkage bit; GND:linkage bit\n" " );\n" " attribute PIN_MAP of DEMO : entity is PHYSICAL_PIN_MAP;\n" " constant PKG : PIN_MAP_STRING :=\n" " \"TCK:A1,\" & \"TDI:A2,\" & \"TDO:A3,\" & \"TMS:A4,\" &\n" " \"IO1:B1,\" & \"VDD:C1,\" & \"GND:C2\";\n" " attribute TAP_SCAN_IN of TDI : signal is true;\n" " attribute TAP_SCAN_MODE of TMS : signal is true;\n" " attribute TAP_SCAN_OUT of TDO : signal is true;\n" " attribute TAP_SCAN_CLOCK of TCK : signal is (10.0e6, BOTH);\n" " attribute INSTRUCTION_LENGTH of DEMO : entity is 2;\n" " attribute INSTRUCTION_OPCODE of DEMO : entity is \"BYPASS (11), IDCODE (10)\";\n" " attribute IDCODE_REGISTER of DEMO : entity is \"00010010001101000101000000001111\";\n" " attribute BOUNDARY_LENGTH of DEMO : entity is 1;\n" " attribute BOUNDARY_REGISTER of DEMO : entity is \"0 (BC_1, IO1, bidir, X)\";\n" "end DEMO;\n"; TEST_CASE("BsdlModel parses a buffer into essim pin vocabulary") { BsdlModel m = BsdlModel::from_buffer(DEMO_BSDL, "demo.bsd"); REQUIRE(m.valid()); CHECK(m.entity() == "DEMO"); CHECK(m.ports().size() == 7); } TEST_CASE("apply_bsdl binds by port name and sets each pin spec") { BsdlModel m = BsdlModel::from_buffer(DEMO_BSDL, "demo.bsd"); REQUIRE(m.valid()); Part part("U1"); for (const char *n : {"TCK", "TDI", "TDO", "TMS", "IO1", "VDD", "GND"}) part.add(new Pin(n)); BsdlApplyReport r = apply_bsdl(&part, m); CHECK(r.pins_total == 7); CHECK(r.bound == 7); CHECK(r.unbound == 0); Pin *tck = part.get("TCK"); CHECK(tck->spec.function == PinFunction::JtagTck); CHECK(tck->spec.direction == PinDirection::In); CHECK(tck->spec.source == SpecSource::Bsdl); CHECK(tck->spec.pad == "A1"); CHECK(part.get("TDI")->spec.function == PinFunction::JtagTdi); CHECK(part.get("TDO")->spec.function == PinFunction::JtagTdo); CHECK(part.get("TDO")->spec.direction == PinDirection::Out); CHECK(part.get("TMS")->spec.function == PinFunction::JtagTms); Pin *io1 = part.get("IO1"); CHECK(io1->spec.function == PinFunction::Signal); CHECK(io1->spec.direction == PinDirection::Bidir); // Linkage pins classified, and the derived expected net type follows. Pin *vdd = part.get("VDD"); CHECK(vdd->spec.function == PinFunction::Power); CHECK(vdd->spec.direction == PinDirection::Power); CHECK(vdd->expected_signal_type() == SignalType::Power); Pin *gnd = part.get("GND"); CHECK(gnd->spec.function == PinFunction::Ground); CHECK(gnd->expected_signal_type() == SignalType::GndShield); } TEST_CASE("apply_bsdl falls back to the physical pad when names are balls") { BsdlModel m = BsdlModel::from_buffer(DEMO_BSDL, "demo.bsd"); REQUIRE(m.valid()); // A part whose pins are named by package ball, not by signal. Part part("U2"); for (const char *n : {"A1", "A2", "A3", "A4", "B1", "C1", "C2"}) part.add(new Pin(n)); BsdlApplyReport r = apply_bsdl(&part, m); CHECK(r.bound == 7); CHECK(r.unbound == 0); CHECK(part.get("A1")->spec.function == PinFunction::JtagTck); // TCK:A1 CHECK(part.get("C1")->spec.function == PinFunction::Power); // VDD:C1 CHECK(part.get("C2")->spec.function == PinFunction::Ground); // GND:C2 }