Sai Kumar Taraka
feat: Add enhanced ML model with retrieval-augmented generation
a9127d4
import yaml from "js-yaml";
const PROTOCOLS = ["uart", "spi", "i2c", "axi4lite", "apb", "wishbone", "custom"];
const DEFAULT_YAML = `# UVM Testbench Generator — UART 16550 Example
# Production-ready specification for full UVM TB generation
design_name: uart
protocol: uart
version: "1.5"
vendor: "Verification IP"
description: "16550 Compatible UART Controller"
clock_reset:
clock: clk
reset: rst_n
reset_active: 0
interfaces:
- name: uart_intf
signals:
- { name: wb_cyc, direction: input, width: 1, description: "Wishbone cycle" }
- { name: wb_stb, direction: input, width: 1, description: "Wishbone strobe" }
- { name: wb_we, direction: input, width: 1, description: "Write enable" }
- { name: wb_addr, direction: input, width: 3, description: "Address bus" }
- { name: wb_data_o, direction: input, width: 8, description: "Write data" }
- { name: wb_data_i, direction: output, width: 8, description: "Read data" }
- { name: wb_ack, direction: output, width: 1, description: "Acknowledge" }
- { name: uart_tx, direction: output, width: 1, description: "Serial transmit" }
- { name: uart_rx, direction: input, width: 1, description: "Serial receive" }
- { name: cts_n, direction: input, width: 1, description: "Clear to send" }
- { name: rts_n, direction: output, width: 1, description: "Request to send" }
- { name: uart_intr, direction: output, width: 1, description: "Interrupt output" }
registers:
- name: RBR_THR
address: '0x00'
access: rw
description: "Receiver Buffer / Transmitter Holding"
fields:
- { name: data, bits: '7:0', access: rw, description: "Data byte" }
- name: IER
address: '0x01'
access: rw
description: "Interrupt Enable Register"
fields:
- { name: erbfi, bits: '0', description: "Enable RX data available interrupt" }
- { name: etbei, bits: '1', description: "Enable TX holding register empty interrupt" }
- { name: elsi, bits: '2', description: "Enable RX line status interrupt" }
- { name: edssi, bits: '3', description: "Enable modem status interrupt" }
- name: IIR
address: '0x02'
access: ro
description: "Interrupt Identification Register"
fields:
- { name: int_id, bits: '3:0', description: "Interrupt type identifier" }
- name: LCR
address: '0x03'
access: rw
description: "Line Control Register"
fields:
- { name: wls, bits: '1:0', description: "Word length select (5-8 bits)" }
- { name: stb, bits: '2', description: "Stop bits (0=1, 1=1.5/2)" }
- { name: pen, bits: '3', description: "Parity enable" }
- { name: eps, bits: '4', description: "Even parity select" }
- { name: sp, bits: '5', description: "Stick parity" }
- { name: bc, bits: '6', description: "Break control" }
- { name: dlab, bits: '7', description: "Divisor latch access bit" }
- name: MCR
address: '0x04'
access: rw
description: "Modem Control Register"
fields:
- { name: dtr, bits: '0', description: "Data Terminal Ready" }
- { name: rts, bits: '1', description: "Request To Send" }
- { name: out1, bits: '2', description: "Output 1" }
- { name: out2, bits: '3', description: "Output 2" }
- { name: loop, bits: '4', description: "Loopback mode enable" }
- name: LSR
address: '0x05'
access: ro
description: "Line Status Register"
fields:
- { name: dr, bits: '0', description: "Data Ready" }
- { name: oe, bits: '1', description: "Overrun Error" }
- { name: pe, bits: '2', description: "Parity Error" }
- { name: fe, bits: '3', description: "Framing Error" }
- { name: bi, bits: '4', description: "Break Interrupt" }
- { name: thre, bits: '5', description: "TX Holding Register Empty" }
- { name: temt, bits: '6', description: "Transmitter Empty" }
- { name: err, bits: '7', description: "Error in RX FIFO" }
- name: MSR
address: '0x06'
access: ro
description: "Modem Status Register"
fields:
- { name: dcts, bits: '0', description: "Delta Clear To Send" }
- { name: cts, bits: '4', description: "Clear To Send" }
- name: SCR
address: '0x07'
access: rw
description: "Scratch Register"
fields:
- { name: scratch, bits: '7:0', description: "Scratch pad for testing" }
`;
export function parseYAML(text) {
const doc = yaml.load(text);
return doc || {};
}
export function validateYAML(text) {
const errors = [];
try {
const doc = yaml.load(text);
if (!doc || typeof doc !== "object") {
errors.push("Root must be a YAML mapping (object)");
return errors;
}
if (!doc.design_name) errors.push("Missing required field: design_name");
if (!doc.interfaces || !doc.interfaces.length)
errors.push("At least one interface required");
if (doc.interfaces) {
doc.interfaces.forEach((iface, i) => {
if (!iface.name) errors.push(`Interface #${i + 1} missing name`);
if (!Array.isArray(iface.signals) || iface.signals.length === 0)
errors.push(`Interface "${iface.name || "#" + (i + 1)}" has no signals`);
});
}
if (doc.registers) {
doc.registers.forEach((reg, i) => {
if (!reg.name) errors.push(`Register #${i + 1} missing name`);
if (!reg.address) errors.push(`Register "${reg.name || "#" + (i + 1)}" missing address`);
if (reg.address && !/^0x[0-9a-fA-F]+$/.test(String(reg.address)))
errors.push(`Register "${reg.name}" address should be hex (0x...)`);
});
}
} catch (e) {
errors.push(`YAML parse error: ${e.message}`);
}
return errors;
}
export function toYAML(obj) {
return yaml.dump(obj, { indent: 2, lineWidth: 120, noRefs: true });
}
export { PROTOCOLS, DEFAULT_YAML };