diff --git a/.gitea/workflows/label.yml b/.gitea/workflows/label.yml new file mode 100644 index 0000000..78023b9 --- /dev/null +++ b/.gitea/workflows/label.yml @@ -0,0 +1,54 @@ +name: 自动生成 label + +# main 分支推送 +on: + push: + branches: + - main + +jobs: + Generate-label: + runs-on: node-21 + steps: + - name: 获取仓库 + uses: http://shenjack.top:5100/gitea-server/checkout@v4 + + - name: pip + run: | + cd .. + git clone http://shenjack.top:5100/gitea-server/python-packs.git + cd python-packs + python3 -m ensurepip + cd ../ARS-docs + + - name: 安装依赖 + run: | + python3 -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple + python3 -m pip install -U pip + python3 -m pip install -U -r scripts/requirement.txt + ls . -la + ls scripts + + - name: 生成 label + run: | + python3 scripts/parse-label.py + cp build/tags.toml modules/tags.toml + + - name: 检查是否有改动 + run: | + git config user.name gitea-actions + git config user.email gitea-action@shenjack.top + if [ -n "$(git status --porcelain)" ]; then + git add . + git commit -m "gen by python script" + # 创建并切换到deploy分支 + git checkout -b deploy + # 将更改添加到deploy分支的最新提交 + git commit --amend --no-edit + # 推送到deploy分支 + git push origin HEAD --force + else + echo "工作区没有改动" + fi + +# https://gitea.com/actions/gitea-release-action diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..59088f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +venv +env +*__pycache__* +build \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..9be2489 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,9 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +* \ No newline at end of file diff --git a/load.md b/load.md new file mode 100644 index 0000000..70e8a3d --- /dev/null +++ b/load.md @@ -0,0 +1,5 @@ +# 如何使用这个索引 + +## 网页 + +## git diff --git a/modules/CCA/CCA-vertial-20gt-32bit/readme.md b/modules/CCA/CCA-vertial-20gt-32bit/readme.md index ef90aaa..7a1628d 100644 --- a/modules/CCA/CCA-vertial-20gt-32bit/readme.md +++ b/modules/CCA/CCA-vertial-20gt-32bit/readme.md @@ -1,4 +1,8 @@ -# 32位 封闭进位加法器 +--- +module +--- + +# 32位封闭进位加法器 ## 基本描述 @@ -34,21 +38,21 @@ ## 模块参数列表 -| 端口列表 | 位宽 | 位置 | 延迟 | 注释 | -| -------- | --- | ----- | -------- | ---- | -| 输入数据A | 32 | 1 3 1 | 0+2[N mod 8] | 加数A | -| 输入数据B | 32 | 4 3 1 | 0+2[N mod 8] | 加数B | -| 输出数据 | 32 | 5 2 9 | 4+2[N mod 8] | 和 | -| 进位输入 | 1 | 3 2 6 | 0 | 低位进位 | -| 标志位 | 1 | 5 65 9 | 11 | 溢出 | +| 端口列表 | 位宽 | 位置 | 延迟 | 注释 | +| --------- | ---- | ------ | ------------ | -------- | +| 输入数据A | 32 | 1 3 1 | 0+2[N mod 8] | 加数A | +| 输入数据B | 32 | 4 3 1 | 0+2[N mod 8] | 加数B | +| 输出数据 | 32 | 5 2 9 | 4+2[N mod 8] | 和 | +| 进位输入 | 1 | 3 2 6 | 0 | 低位进位 | +| 标志位 | 1 | 5 65 9 | 11 | 溢出 | ## 模块指标列表 -| 指标项目 | 参数 | 指标项目 | 参数 | -| ------------------ | --- | ---------------- | --- | -| 火把 | 有 | 2rt流水线 | 不支持 | -| 活塞 | 无 | 红石粉 | 有 | -| 侦测器 | 无 | 容器 | 无 | -| 应用漏斗、投掷器 | 无 | 墙电、水电、光电 | 无 | | | +| 指标项目 | 参数 | 指标项目 | 参数 | +| ---------------- | ---- | ---------------- | ------ | +| 火把 | 有 | 2rt流水线 | 不支持 | +| 活塞 | 无 | 红石粉 | 有 | +| 侦测器 | 无 | 容器 | 无 | +| 应用漏斗、投掷器 | 无 | 墙电、水电、光电 | 无 | 模块分支:封闭进位加法器 diff --git a/scripts/parse-label.py b/scripts/parse-label.py new file mode 100644 index 0000000..7823893 --- /dev/null +++ b/scripts/parse-label.py @@ -0,0 +1,152 @@ +from pathlib import Path +from typing import Union, Callable +from pprint import pprint + +import mistune + +from qtoml.encoder import dumps +from qtoml.decoder import loads +from lib_not_dr import loggers +from lib_not_dr.types.options import Options + + +ast_markdown = mistune.create_markdown(renderer="ast") +ast_type = list[dict[str, Union[str, dict]]] + + +def get_all_iter( + ast: ast_type, type: str, func: Callable[[ast_type], bool] = None +) -> tuple[int, dict]: + for i, node in enumerate(ast): + if node["type"] == type: + if func is not None: + if not func(node): + continue + yield i, node + yield -1, {} + + +def get_text(ast: ast_type) -> str: + """ + 返回第一个找到的字符串 + """ + if ast['type'] == 'text': + return ast['raw'] + elif ast['type'] in ('link', 'block_text', 'list_item', 'list'): + return get_text(ast['children'][0]) + print('unkown type', ast['type'], ast) + + +class TagParser(Options): + module_root: Path + tags: dict[str, list[str]] = {} + tag_map: dict[str, list[str]] = {} + logger: loggers.logger.Logger = None # noqa + + def load_module(self, **kwargs): + for readme in self.module_root.rglob("readme.md"): + self.logger.debug(readme.absolute(), tag="load file") + self.get_module_data(readme) + + tag_toml = dumps(self.tags) + tag_path = self.module_root / ".." / "build" / "tags.toml" + tag_path.parent.mkdir(parents=True, exist_ok=True) + tag_path.touch(exist_ok=True) + with open(tag_path, "w", encoding="utf-8") as file: + file.write(tag_toml) + + def get_module_data(self, module_path: Path): + with open(module_path, "r", encoding="utf-8") as f: + file = f.read() + + ast = ast_markdown(file) + if len(ast) == 0: + return + + if ast[0] != {"type": "thematic_break"}: + # 排除开头不是注释块的 + return + + self.logger.info(f"开始解析 {ast[1]}") + config_code = ast[1].get("raw", "") + config_dict = loads(config_code) + self.logger.trace(config_dict) + + if not (tag_list := config_dict.get("tags")): + self.logger.warn("未找到 tags", tag=str(module_path)) + return + + for tag in tag_list: + if tag not in self.tags: + self.tags[tag] = [module_path.__str__()] + else: + self.tags[tag].append(module_path.__str__()) + + def init(self, **kwargs) -> bool: + self.logger = loggers.get_logger() + self.logger.global_level = 0 + self.load_tags() + return False + + def load_tags(self): + tag_list_path = Path("./tags/readme.md") + if not tag_list_path.exists(): + self.logger.error("未找到 tags/readme.md") + return False + + with open(tag_list_path, "r", encoding="utf-8") as f: + file = f.read() + + tag_ast: ast_type = ast_markdown(file) + start_tag = -1 + # 找到二级标题 + start_tag = get_all_iter( + tag_ast, "heading", lambda node: node["attrs"]["level"] == 2 + ) + start_tag, node = next(start_tag) + if start_tag == -1: + self.logger.error("未找到二级标题") + return False + # 获取 tag + tag_ast: ast_type = tag_ast[start_tag + 1 :] + start_tag = get_all_iter(tag_ast, "list") + start_tag, node = next(start_tag) + if start_tag == -1: + self.logger.error("未找到 tag 列表") + return False + tag_ast: ast_type = [ + item["children"] + for item in tag_ast[start_tag]["children"] + if item.get("type") == "list_item" + ] + # 顺手过滤一下 + for tag in tag_ast: + # self.logger.debug([(item['type'], item['children']) for item in tag]) + this_tag = get_text(tag[0]) + if len(tag) == 1: + # 只有一个 tag, 无别名 + self.tag_map[this_tag] = [this_tag] + self.logger.debug(f'添加 tag {this_tag}') + # len > 1 + elif len(tag) >= 1: + # 寻找 "别名" + tag_names = tag[1]['children'] + tag_list_start = get_all_iter(tag_names, 'list_item', lambda ast: get_text(ast) == '别名') + tag_list_start, node = next(tag_list_start) + if tag_list_start == -1: + continue + sub_names = [] + for sub_name in node['children'][1]['children']: + sub_names.append(get_text(sub_name)) + self.logger.debug(f"添加 tag {this_tag} 和别名 {sub_names}") + self.tag_map[this_tag] = sub_names + # 获取 tag 列表 + self.logger.info(f'可用 tag: {self.tag_map}') + with open('./tags/tag.toml', 'w', encoding='utf-8') as file: + file.write(dumps(self.tag_map)) + + +if __name__ == "__main__": + parser = TagParser(module_root=Path("modules")) + parser.load_module() + parser.logger.info(parser.tags) diff --git a/scripts/requirement.txt b/scripts/requirement.txt new file mode 100644 index 0000000..058e70d --- /dev/null +++ b/scripts/requirement.txt @@ -0,0 +1,3 @@ +mistune +lib-not-dr +qtoml diff --git a/tags/readme.md b/tags/readme.md index e30f818..4543886 100644 --- a/tags/readme.md +++ b/tags/readme.md @@ -1,26 +1,36 @@ # 标签索引 + ![标签索引logo](../assets/image/tag_index.png) -##s 所有可用标签: - - [小型模块](./tags/small_module.md) : 方块数量小于10000的模块 - - [中型模块](./tags/middle_size_module.md) : 方块数量在10001-100000之间的模块。 - - [大型模块](./tags/large_module.md) : 方块数量>100000的模块。 - - [算术单元](./tags/au.md) : 具有运算功能的模块。 - - [加/减法器](./tags/adder_or_subtractor.md) : 具有加/减法功能的模块。 - - [ALU (算逻单元) ](./tags/alu.md) : 算术逻辑单元 - - [显示模块](./tags/display_module.md) : 具备显示功能的模块。 - - [存储模块](./tags/storage_module.md) : 具备存储功能的模块。 - - [数码管](./tags/digital_display.md) : 显示数字的专用模块。 - - [成品模块](./tags/completed_module.md) : 已经完成设计的模块,如CPU - - [一级模块](./tags/primary_module.md) : 组成整个模块的次级模块。如ALU (算术逻辑单元) ,PC (程序计数器) ,MM (主存) 等。 - - [二级模块](./tags/secondary_module.md) : 次级模块的次级模块。如CCA (进位取消全加器) ,RAM (随机存储器) ,ROM (只读存储器) 等。 - - [子模块](./tags/submodule.md) : 二级模块的次级模块。如单个逻辑门,导线等。 - - [Java版](./tags/je.md) : Java版模块 - - [基岩版](./tags/be.md) : 基岩版模块。 - - [版本特性](./tags/version_feature.md) : 利用了版本特性的模块。 - - [2rt流水](./tags/2rt_pipeline.md) : 支持2rt流水线的模块。 - - [时序严格](./tags/strict_timing.md) : 对于电路时序要求严格的模块。 - - [无容器](./tags/no_container.md) : 没有容器的模块。 - - [静音](./tags/silent.md) : 不会发出响声的模块。 - - [单片](./tags/single_chip.md) : 1高或1宽的模块。 - - [传统红石](./tags/traditional_redstone.md) : 仅使用红石方块特性,不使用墙电,水电,树电,脚电等其他特性的模块。 -  + +## 所有可用标签 + +- [小型模块](./tags/small_module.md) + - 方块数量小于10000的模块 + - 别名 + - 小模块 +- [中型模块](./tags/middle_size_module.md) : 方块数量在10001-100000之间的模块。 +- [大型模块](./tags/large_module.md) : 方块数量>100000的模块。 +- [算术单元](./tags/au.md) : 具有运算功能的模块。 +- [加/减法器](./tags/adder_or_subtractor.md) : 具有加/减法功能的模块。 +- [ALU (算逻单元)](./tags/alu.md) : 算术逻辑单元 +- [显示模块](./tags/display_module.md) : 具备显示功能的模块。 +- [存储模块](./tags/storage_module.md) : 具备存储功能的模块。 +- [数码管](./tags/digital_display.md) : 显示数字的专用模块。 +- [成品模块](./tags/completed_module.md) : 已经完成设计的模块,如CPU +- [一级模块](./tags/primary_module.md) : 组成整个模块的次级模块。如ALU (算术逻辑单元) ,PC (程序计数器) ,MM (主存) 等。 +- [二级模块](./tags/secondary_module.md) : 次级模块的次级模块。如CCA (进位取消全加器) ,RAM (随机存储器) ,ROM (只读存储器) 等。 +- [子模块](./tags/submodule.md) : 二级模块的次级模块。如单个逻辑门,导线等。 +- [Java版](./tags/je.md) : Java版模块 +- [基岩版](./tags/be.md) : 基岩版模块。 +- [版本特性](./tags/version_feature.md) : 利用了版本特性的模块。 +- [2rt流水](./tags/2rt_pipeline.md) : 支持2rt流水线的模块。 +- [时序严格](./tags/strict_timing.md) : 对于电路时序要求严格的模块。 +- [无容器](./tags/no_container.md) : 没有容器的模块。 +- [静音](./tags/silent.md) : 不会发出响声的模块。 +- [单片](./tags/single_chip.md) : 1高或1宽的模块。 +- [传统红石](./tags/traditional_redstone.md) : 仅使用红石方块特性,不使用墙电,水电,树电,脚电等其他特性的模块。 +- 测试 tag + - 只是用来测试的 + - 别名 + - 测试1 + - 测试2