A => +73 -0
@@ 0,0 1,73 @@
use crate::display_elements::{DisplayColor, DisplayFormat};
#[derive(Eq, PartialEq, Debug)]
pub enum Operation {
UpdateContext(ContextUpdate),
AddEmpty,
AddSignal(String),
}
#[derive(Eq, PartialEq, Debug)]
pub enum ContextUpdate {
UpdateColor(Option<DisplayColor>),
UpdateFormat(DisplayFormat),
SetOmit(bool),
Reset,
}
pub struct CommentParser {}
impl CommentParser {
pub fn parse_comment(comment: &str) -> Vec<Operation> {
comment
.split(['\n', ','].as_ref())
.map(|token| Self::parse_token(token.trim()))
.filter(|operation| operation.is_some())
.into_iter()
.map(|operation| operation.unwrap())
.collect()
}
fn parse_token(token: &str) -> Option<Operation> {
Some(match token {
"omit" => Operation::UpdateContext(ContextUpdate::SetOmit(true)),
"empty" => Operation::AddEmpty,
"reset" => Operation::UpdateContext(ContextUpdate::Reset),
_ if token.starts_with("add signal ") => {
Operation::AddSignal(token["add signal ".len()..].to_owned())
}
_ if token.starts_with("format ") => Operation::UpdateContext(
ContextUpdate::UpdateFormat(Self::parse_format(&token["format ".len()..])),
),
_ if token.starts_with("color ") => Operation::UpdateContext(
ContextUpdate::UpdateColor(Self::parse_color(&token["color ".len()..])),
),
_ => return None,
})
}
fn parse_format(format: &str) -> DisplayFormat {
match format {
"hex" => DisplayFormat::Hex,
"decimal" => DisplayFormat::Decimal,
"signed decimal" => DisplayFormat::SignedDecimal,
"binary" => DisplayFormat::Binary,
_ => DisplayFormat::Decimal,
}
}
fn parse_color(color: &str) -> Option<DisplayColor> {
Some(match color {
"normal" => DisplayColor::Normal,
"red" => DisplayColor::Red,
"orange" => DisplayColor::Orange,
"yellow" => DisplayColor::Yellow,
"green" => DisplayColor::Green,
"blue" => DisplayColor::Blue,
"indigo" => DisplayColor::Indigo,
"violet" => DisplayColor::Violet,
"cycle" => DisplayColor::Cycle,
_ => return None,
})
}
}
M src/display_elements.rs => src/display_elements.rs +30 -116
@@ 1,47 1,13 @@
-use std::{slice::Iter, fmt::Display};
+use std::fmt::Display;
-#[derive(Eq, PartialEq, Clone)]
-pub enum DisplayElement {
- Signal(Signal),
- Empty(Vec<DisplayOption>)
-}
-
-#[derive(Eq, PartialEq, Clone, Copy)]
+#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum DisplayOption {
Color(DisplayColor),
Format(DisplayFormat),
- Omit
-}
-
-#[derive(Eq, PartialEq, Clone)]
-pub struct Signal {
- name: String,
- options: Vec<DisplayOption>
-}
-
-impl From<&str> for Signal {
- fn from(value: &str) -> Self {
- Self {
- name: value.to_owned(),
- options: vec![]
- }
- }
-}
-
-#[derive(Eq, PartialEq, Clone)]
-pub struct Entity {
- name: String,
- architecture: Option<Architecture>,
+ Omit,
}
-#[derive(Eq, PartialEq, Clone)]
-pub struct Architecture {
- name: String,
- entity_name: String,
- signals: Vec<Signal>
-}
-
-#[derive(Eq, PartialEq, Copy, Clone)]
+#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum DisplayColor {
Normal,
Red,
@@ 56,21 22,25 @@ pub enum DisplayColor {
impl Display for DisplayColor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", match self {
- DisplayColor::Normal => "Normal",
- DisplayColor::Red => "Red",
- DisplayColor::Orange => "Orange",
- DisplayColor::Yellow => "Yellow",
- DisplayColor::Green => "Green",
- DisplayColor::Blue => "Blue",
- DisplayColor::Indigo => "Indigo",
- DisplayColor::Violet => "Violet",
- DisplayColor::Cycle => "Cycle",
- })
+ write!(
+ f,
+ "{}",
+ match self {
+ DisplayColor::Normal => "Normal",
+ DisplayColor::Red => "Red",
+ DisplayColor::Orange => "Orange",
+ DisplayColor::Yellow => "Yellow",
+ DisplayColor::Green => "Green",
+ DisplayColor::Blue => "Blue",
+ DisplayColor::Indigo => "Indigo",
+ DisplayColor::Violet => "Violet",
+ DisplayColor::Cycle => "Cycle",
+ }
+ )
}
}
-#[derive(Eq, PartialEq, Copy, Clone)]
+#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum DisplayFormat {
Hex,
Decimal,
@@ 80,71 50,15 @@ pub enum DisplayFormat {
impl Display for DisplayFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", match self {
- DisplayFormat::Hex => "Hex",
- DisplayFormat::Decimal => "Decimal",
- DisplayFormat::SignedDecimal => "SignedDecimal",
- DisplayFormat::Binary => "Binary",
- })
- }
-}
-
-impl Signal {
- pub fn new(name: String, options: Vec<DisplayOption>) -> Self {
- Self {
- name,
- options
- }
- }
-
- pub fn name(&self) -> &str {
- &self.name
- }
-
- pub fn options(&self) -> Iter<'_, DisplayOption> {
- self.options.iter()
- }
-}
-
-impl Entity {
- pub fn new(name: String) -> Self {
- Self {
- name,
- architecture: None
- }
- }
-
- pub fn name(&self) -> &str {
- &self.name
- }
-
- pub fn add_architecture(&mut self, architecture: Architecture) {
- self.architecture = Some(architecture);
- }
-
- pub fn architecture(&self) -> Option<&Architecture> {
- self.architecture.as_ref()
- }
-}
-
-impl Architecture {
- pub fn new(name: String, entity_name: String, signals: Vec<Signal>) -> Self {
- Self {
- name,
- entity_name,
- signals,
- }
- }
-
- pub fn signals(&self) -> Iter<'_, Signal> {
- self.signals.iter()
- }
-
- pub fn name(&self) -> &str {
- &self.name
- }
-
- pub fn entity_name(&self) -> &str {
- &self.entity_name
+ write!(
+ f,
+ "{}",
+ match self {
+ DisplayFormat::Hex => "Hex",
+ DisplayFormat::Decimal => "Decimal",
+ DisplayFormat::SignedDecimal => "SignedDecimal",
+ DisplayFormat::Binary => "Binary",
+ }
+ )
}
}
M src/file_parser.rs => src/file_parser.rs +133 -158
@@ 1,131 1,128 @@
-use vhdl_lang::{Source, syntax::{tokens::{TokenStream, Tokenizer, Kind, Comment}, Symbols}, Diagnostic, data::{Contents, ContentReader}};
-
-use crate::display_elements::{DisplayColor, Entity, Architecture, Signal, DisplayOption, DisplayFormat};
-
-#[derive(PartialEq, Eq, Clone)]
-struct Context {
- color: Option<DisplayColor>,
- omit: bool
+use vhdl_lang::{
+ data::{ContentReader, Contents},
+ syntax::{
+ tokens::{Kind, TokenStream, Tokenizer},
+ Symbols,
+ },
+ Diagnostic, Source,
+};
+
+#[derive(Eq, PartialEq)]
+pub struct ParsedEntity {
+ name: String,
+ architecture: Option<ParsedArchitecture>,
}
-pub struct FileParser<'a> {
- diagnostics: Vec<Diagnostic>,
- stream: TokenStream<'a>,
+impl ParsedEntity {
+ pub fn name(&self) -> &str {
+ &self.name[..]
+ }
- entities: Vec<Entity>,
- current_entity: usize
+ pub fn architecture(&self) -> Option<&ParsedArchitecture> {
+ self.architecture.as_ref()
+ }
}
-#[derive(Debug)]
-pub enum ParseError {
- EntityNotPresent,
- ArchitectureNotFound,
- ParsingError(Diagnostic),
- EndOfFile,
+#[derive(Eq, PartialEq)]
+pub struct ParsedArchitecture {
+ name: String,
+ entity_name: String,
+ parts: Vec<ParsedArchitecturePart>,
}
-impl From<Diagnostic> for ParseError {
- fn from(value: Diagnostic) -> Self {
- Self::ParsingError(value)
+impl ParsedArchitecture {
+ pub fn name(&self) -> &str {
+ &self.name
}
-}
-impl From<&Context> for Vec<DisplayOption> {
- fn from(value: &Context) -> Self {
- let mut options = vec![];
-
- if value.omit {
- options.push(DisplayOption::Omit);
- }
-
- if let Some(color) = value.color {
- options.push(DisplayOption::Color(color));
- }
+ pub fn entity_name(&self) -> &str {
+ &self.entity_name
+ }
- options
+ pub fn parts(&self) -> &Vec<ParsedArchitecturePart> {
+ &self.parts
}
}
-impl<'a> FileParser<'a> {
- pub fn new(source: &'a Source, contents: &'a Contents, symbols: &'a Symbols) -> Self {
- let mut diagnostics = vec![];
- let tokenizer = Tokenizer::new(symbols, source, ContentReader::new(contents));
- let stream = TokenStream::new(tokenizer, &mut diagnostics);
+#[derive(PartialEq, Eq)]
+pub struct ParsedSignal {
+ name: String,
+ signal_type: String,
+ comment: Option<String>,
+}
- Self {
- diagnostics,
- stream,
- entities: vec![],
- current_entity: 0,
- }
+impl ParsedSignal {
+ pub fn name(&self) -> &str {
+ &self.name
}
- pub fn find_next_entity(&mut self) -> Result<Entity, ParseError> {
- if self.current_entity < self.entities.len() {
- self.current_entity += 1;
- return Ok(self.entities[self.current_entity - 1].clone());
- }
-
- if self.stream.skip_until(|k| k == Kind::Entity || k == Kind::Architecture).is_err() {
- return Err(ParseError::EndOfFile);
- }
-
- if self.stream.peek_kind().unwrap() == Kind::Entity {
- let entity = Self::parse_entity(&mut self.stream)?;
- self.entities.push(entity.clone());
- self.current_entity += 1;
-
- Ok(entity)
- } else {
- let architecture = Self::parse_architecture(&mut self.stream)?;
-
- if let Some(entity) = self.entities.iter_mut().find(|e| e.name() == architecture.entity_name()) {
- entity.add_architecture(architecture);
- }
+ pub fn signal_type(&self) -> &str {
+ &self.signal_type
+ }
- self.find_next_entity()
- }
+ pub fn comment(&self) -> Option<&str> {
+ self.comment.as_deref()
}
+}
- pub fn parse_entity_architecture(&mut self, mut entity: Entity) -> Result<Entity, ParseError> {
- let Some(found_entity) = self.entities.iter_mut().find(|e| e.name() == entity.name()) else {
- return Err(ParseError::EntityNotPresent);
- };
+#[derive(PartialEq, Eq)]
+pub enum ParsedArchitecturePart {
+ Signal(ParsedSignal),
+ Comment(String),
+}
- if entity.architecture().is_some() {
- return Ok(entity);
- }
+pub struct FileParser {}
- if found_entity.architecture().is_some() {
- return Ok(found_entity.clone());
- }
-
- if self.stream.skip_until(|k| k == Kind::Entity || k == Kind::Architecture).is_err() {
- return Err(ParseError::EndOfFile);
- }
+#[derive(Debug)]
+pub enum ParseError {
+ ArchitectureWithoutEntity,
+ ParsingError(Diagnostic),
+ EndOfFile,
+}
- if self.stream.peek_kind().unwrap() == Kind::Entity {
- let entity = Self::parse_entity(&mut self.stream)?;
- self.entities.push(entity.clone());
- return self.parse_entity_architecture(entity)
- }
+impl From<Diagnostic> for ParseError {
+ fn from(value: Diagnostic) -> Self {
+ Self::ParsingError(value)
+ }
+}
- let architecture = Self::parse_architecture(&mut self.stream)?;
- if architecture.entity_name() == entity.name() {
- entity.add_architecture(architecture.clone());
- found_entity.add_architecture(architecture);
+impl FileParser {
+ pub fn parse_file(
+ source: &Source,
+ contents: &Contents,
+ symbols: &Symbols,
+ ) -> Result<Vec<ParsedEntity>, ParseError> {
+ let mut entities = vec![];
+ let mut diagnostics = vec![];
+ let tokenizer = Tokenizer::new(symbols, source, ContentReader::new(contents));
+ let mut stream = TokenStream::new(tokenizer, &mut diagnostics);
- return Ok(entity);
- }
+ while stream
+ .skip_until(|k| k == Kind::Entity || k == Kind::Architecture)
+ .is_ok()
+ {
+ let kind = stream.peek_kind().unwrap();
- if let Some(matched_entity) = self.entities.iter_mut().find(|e| e.name() == architecture.entity_name()) {
- matched_entity.add_architecture(architecture);
+ match kind {
+ Kind::Entity => {
+ entities.push(Self::parse_entity(&mut stream)?);
+ }
+ Kind::Architecture => {
+ let architecture = Self::parse_architecture(&mut stream)?;
+ let entity = entities
+ .iter_mut()
+ .find(|e| e.name == architecture.entity_name)
+ .ok_or(ParseError::ArchitectureWithoutEntity)?;
+ entity.architecture = Some(architecture);
+ }
+ _ => panic!("Wrong kind. Skip until bugged."),
+ }
}
- self.parse_entity_architecture(entity)
+ Ok(entities)
}
- fn parse_architecture(stream: &mut TokenStream) -> Result<Architecture, ParseError> {
+ fn parse_architecture(stream: &mut TokenStream) -> Result<ParsedArchitecture, ParseError> {
stream.expect_kind(Kind::Architecture)?;
let architecture_name = Self::parse_identifier(stream)?;
@@ 136,31 133,41 @@ impl<'a> FileParser<'a> {
stream.expect_kind(Kind::Is)?;
- let mut context = Context { color: None, omit: false };
- let mut signals = vec![];
+ let mut parts: Vec<ParsedArchitecturePart> = vec![];
- while !stream.next_kind_is(Kind::Begin) {
+ loop {
let token = stream.peek().ok_or(ParseError::EndOfFile)?;
if let Some(comments) = &token.comments {
for comment in &comments.leading {
- Self::update_context(&mut context, comment);
+ parts.push(ParsedArchitecturePart::Comment(comment.value.clone()));
}
}
match token.kind {
- Kind::Signal => signals.append(Self::parse_signals(stream, &context)?.as_mut()),
+ Kind::Signal => parts.extend(
+ Self::parse_signals(stream)?
+ .into_iter()
+ .map(|s| ParsedArchitecturePart::Signal(s)),
+ ),
Kind::Begin => break,
_ => stream.skip(),
}
}
- let architecture = Architecture::new(architecture_name, entity_name, signals);
+ stream.skip_until(|k| k == Kind::Architecture)?;
+ stream.skip_until(|k| k == Kind::SemiColon)?;
+
+ let architecture = ParsedArchitecture {
+ name: architecture_name,
+ entity_name,
+ parts,
+ };
Ok(architecture)
}
- fn parse_signals(stream: &mut TokenStream, context: &Context) -> Result<Vec<Signal>, ParseError> {
+ fn parse_signals(stream: &mut TokenStream) -> Result<Vec<ParsedSignal>, ParseError> {
stream.expect_kind(Kind::Signal)?;
let mut signal_names = vec![];
@@ 178,36 185,37 @@ impl<'a> FileParser<'a> {
stream.skip_until(|k| k == Kind::SemiColon)?;
let semicolon_token = stream.peek().ok_or(ParseError::EndOfFile)?;
- let options: Vec<DisplayOption> = if let Some(comments) = &semicolon_token.comments {
- if let Some(trailing) = &comments.trailing {
- let mut context = context.clone();
- Self::update_context(&mut context, trailing);
- (&context).into()
- } else {
- context.into()
- }
- } else {
- context.into()
- };
+ let comment = semicolon_token.comments.as_ref().and_then(|comments| {
+ comments
+ .trailing
+ .as_ref()
+ .map(|trailing| trailing.value.clone())
+ });
let mut signals = vec![];
for signal_name in signal_names {
- let mut options = options.clone();
- if signal_type.starts_with("std_logic_vector") {
- options.push(DisplayOption::Format(DisplayFormat::Binary));
- }
-
- signals.push(Signal::new(signal_name, options));
+ signals.push(ParsedSignal {
+ name: signal_name,
+ signal_type: signal_type.clone(),
+ comment: comment.clone(),
+ });
}
Ok(signals)
}
- fn parse_entity(stream: &mut TokenStream) -> Result<Entity, ParseError> {
+ fn parse_entity(stream: &mut TokenStream) -> Result<ParsedEntity, ParseError> {
stream.expect_kind(Kind::Entity)?;
let name = Self::parse_identifier(stream)?;
- Ok(Entity::new(name))
+
+ stream.skip_until(|k| k == Kind::Entity)?;
+ stream.skip_until(|k| k == Kind::SemiColon)?;
+
+ Ok(ParsedEntity {
+ name,
+ architecture: None,
+ })
}
fn parse_identifier(stream: &mut TokenStream) -> Result<String, ParseError> {
@@ 218,37 226,4 @@ impl<'a> FileParser<'a> {
Ok(identifier.item.name_utf8())
}
-
- fn update_context(context: &mut Context, comment: &Comment) {
- let commands = comment.value.split(['\n', ','].as_ref());
-
- for command in commands {
- match command.trim() {
- "omit" => context.omit = true,
- "reset" => {
- context.color = None;
- context.omit = false;
- },
- _ if command.trim().starts_with("color ") => {
- let color = command["color ".len()..].trim();
-
- let color = match color {
- "normal" => DisplayColor::Normal,
- "red" => DisplayColor::Red,
- "orange" => DisplayColor::Orange,
- "yellow" => DisplayColor::Yellow,
- "green" => DisplayColor::Green,
- "blue" => DisplayColor::Blue,
- "Indigo" => DisplayColor::Indigo,
- "Violet" => DisplayColor::Violet,
- "Cycle" => DisplayColor::Cycle,
- _ => DisplayColor::Normal,
- };
-
- context.color = Some(color);
- },
- _ => ()
- }
- }
- }
}
M src/main.rs => src/main.rs +150 -36
@@ 1,16 1,19 @@
-pub mod file_parser;
+pub mod comment_parser;
pub mod display_elements;
+pub mod file_parser;
pub mod tcl_generator;
-use std::{path::PathBuf, fs::File, io::Write};
+use std::{fs::File, io::Write, path::PathBuf};
use clap::{arg, Parser};
-use file_parser::FileParser;
+use comment_parser::{CommentParser, ContextUpdate, Operation};
+use display_elements::DisplayFormat;
+use file_parser::{FileParser, ParsedArchitecturePart, ParsedEntity};
use glob::glob;
use tcl_generator::TclGenerator;
use vhdl_lang::{syntax::Symbols, Source};
-use crate::display_elements::{Signal, DisplayOption, DisplayColor};
+use crate::display_elements::DisplayColor;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
@@ 26,7 29,6 @@ struct Cli {
fn main() {
let cli = Cli::parse();
let find_wildcard = cli.folder.to_str().unwrap().to_owned() + "/**/*.vhd";
- println!("Going to look into {find_wildcard}");
let matching_files = glob(&find_wildcard).unwrap();
@@ 38,52 40,164 @@ fn main() {
let source = Source::from_latin1_file(file.as_path()).unwrap();
let contents = source.contents();
- let mut parser = FileParser::new(&source, &contents, &symbols);
+ let entities = FileParser::parse_file(&source, &contents, &symbols).unwrap();
- match parser.find_next_entity() {
- Ok(entity) => {
- if entity.name() != &cli.testbench[..] {
- continue;
- }
- found = true;
+ for entity in entities {
+ if entity.name() != cli.testbench {
+ continue;
+ }
+ found = true;
+ println!("Found the testbench.");
- println!("Found the testbench.");
+ let tcl = generate_tcl(entity);
- let entity = parser.parse_entity_architecture(entity).unwrap();
- let architecture = entity.architecture().unwrap();
+ let mut file = File::create(cli.output.clone()).unwrap();
+ file.write_all(tcl.as_bytes()).unwrap();
- let mut generator = TclGenerator::new("top.".to_owned() + &cli.testbench + ".");
- generator.add_signal(&Signal::new("clk".to_owned(), vec![DisplayOption::Color(DisplayColor::Indigo)]))
- .add_signal(&Signal::new("rst".to_owned(), vec![DisplayOption::Color(DisplayColor::Indigo)]))
- .add_empty()
- .zoom_out();
+ println!("Generated {}.", cli.output.display());
- for signal in architecture.signals() {
- if signal.name() == "clk" || signal.name() == "rst" {
- continue;
- }
+ break;
+ }
+
+ if found {
+ break;
+ }
+ }
- generator.add_signal(signal);
+ if !found {
+ println!("Could not find the entity.")
+ }
+}
+
+#[derive(Eq, PartialEq, Clone)]
+struct Context {
+ color: Option<DisplayColor>,
+ format: Option<DisplayFormat>,
+ omit: bool,
+}
+
+impl Context {
+ pub fn update<'a>(&mut self, updates: impl Iterator<Item = &'a ContextUpdate>) {
+ for update in updates {
+ match update {
+ ContextUpdate::Reset => {
+ self.color = None;
+ self.format = None;
+ self.omit = false;
+ }
+ ContextUpdate::SetOmit(omit) => {
+ self.omit = omit.clone();
+ }
+ ContextUpdate::UpdateColor(color) => {
+ self.color = color.clone();
}
+ ContextUpdate::UpdateFormat(format) => {
+ self.format = Some(format.clone());
+ }
+ }
+ }
+ }
+
+ pub fn fork<'a>(&self, updates: impl Iterator<Item = &'a ContextUpdate>) -> Context {
+ let mut clone = self.clone();
+ clone.update(updates);
- let generated = generator.generate();
+ clone
+ }
- let mut file = File::create(&cli.output).unwrap();
- file.write_all(generated.as_bytes()).unwrap();
+ pub fn decompose(&self) -> (Option<DisplayColor>, Option<DisplayFormat>, bool) {
+ (self.color, self.format, self.omit)
+ }
+}
- break;
+fn generate_tcl(entity: ParsedEntity) -> String {
+ let architecture = entity.architecture().unwrap();
+
+ let mut generator = TclGenerator::new("top.".to_owned() + entity.name() + ".");
+
+ let mut context = Context {
+ color: None,
+ format: None,
+ omit: false,
+ };
+
+ for part in architecture.parts() {
+ match part {
+ ParsedArchitecturePart::Comment(comment) => {
+ let operations = CommentParser::parse_comment(&comment[..]);
+ if let Some(operation) = operations.first() {
+ if let Operation::AddSignal(signal) = operation {
+ let context_operations = operations.iter().skip(1);
+ add_signal(
+ &mut generator,
+ signal.clone(),
+ None,
+ Some(context_operations),
+ &context,
+ true
+ );
+ } else {
+ let updates = operations.iter().filter_map(|op| match op {
+ Operation::UpdateContext(update) => Some(update),
+ Operation::AddEmpty => {
+ generator.add_empty();
+ None
+ }
+ _ => panic!(),
+ });
+ context.update(updates);
+ }
+ }
},
- Err(err) => {
- println!("{:?}", err);
+ ParsedArchitecturePart::Signal(signal) => {
+ let mut operations = None;
+
+ if let Some(comment) = signal.comment() {
+ operations = Some(CommentParser::parse_comment(comment));
+ }
+
+ add_signal(
+ &mut generator,
+ signal.name().to_owned(),
+ Some(signal.signal_type()),
+ operations.as_ref().map(|x| x.iter()),
+ &context,
+ false
+ );
}
}
+ }
- if found {
- break;
- }
+ generator.generate()
+}
+
+fn add_signal<'a>(
+ generator: &mut TclGenerator,
+ signal: String,
+ signal_type: Option<&str>,
+ operations: Option<impl Iterator<Item = &'a Operation>>,
+ context: &Context,
+ override_omit: bool
+) {
+ let (color, mut format, omit) = if let Some(operations) = operations {
+ let updates = operations.into_iter().filter_map(|op| {
+ if let Operation::UpdateContext(update) = op {
+ Some(update)
+ } else {
+ None
+ }
+ });
+
+ context.fork(updates).decompose()
+ } else {
+ context.decompose()
+ };
+
+ if format.is_none() && signal_type.is_some() && signal_type.unwrap() == "std_logic_vector" {
+ format = Some(DisplayFormat::Binary);
}
- if !found {
- println!("Could not find the entity.")
+ if override_omit || !omit {
+ generator.add_signal(signal, color, format);
}
}
M src/tcl_generator.rs => src/tcl_generator.rs +9 -30
@@ 1,11 1,9 @@
use string_builder::Builder;
-use crate::display_elements::{DisplayColor, DisplayFormat, Signal, DisplayOption};
-
+use crate::display_elements::{DisplayColor, DisplayFormat};
pub struct TclGenerator {
signals: Vec<(String, Option<DisplayColor>, Option<DisplayFormat>)>,
- zoom_out: bool,
signal_prefix: String,
}
@@ 13,28 11,17 @@ impl TclGenerator {
pub fn new(signal_prefix: String) -> Self {
Self {
signals: vec![],
- zoom_out: false,
signal_prefix,
}
}
- pub fn add_signal(&mut self, signal: &Signal) -> &mut Self {
- let mut color = None;
- let mut format = None;
-
- for option in signal.options() {
- match option {
- DisplayOption::Omit => return self,
- DisplayOption::Color(c) => {
- color = Some(c.clone());
- },
- DisplayOption::Format(f) => {
- format = Some(f.clone());
- }
- }
- }
-
- self.signals.push((signal.name().to_owned(), color, format));
+ pub fn add_signal(
+ &mut self,
+ signal: String,
+ color: Option<DisplayColor>,
+ format: Option<DisplayFormat>,
+ ) -> &mut Self {
+ self.signals.push((signal, color, format));
self
}
@@ 43,11 30,6 @@ impl TclGenerator {
self
}
- pub fn zoom_out(&mut self) -> &mut Self {
- self.zoom_out = true;
- self
- }
-
pub fn generate(self) -> String {
let mut builder = Builder::new(300);
@@ 56,7 38,6 @@ impl TclGenerator {
builder.append("gtkwave::/View/Show_Filled_High_Values 1\n");
builder.append("gtkwave::/View/Show_Wave_Highlight 1\n");
builder.append("gtkwave::/View/Show_Mouseover 1\n");
- builder.append("gtkwave::/View/Left_Justified_Signals 1\n");
for signal in self.signals {
if signal.0 == "" {
@@ 84,9 65,7 @@ impl TclGenerator {
}
}
- if self.zoom_out {
- builder.append("gtkwave::/Time/Zoom/Zoom_Best_Fit\n");
- }
+ builder.append("gtkwave::/Time/Zoom/Zoom_Best_Fit\n");
builder.string().unwrap()
}